﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;

using Qing.Lang;

namespace Qing.Std {

    class ToJson : Native {
        public override string Name { get; set; } = "转Json";
        public override string Desc { get; set; } = "参数1-任意，返回字符串；将参数1转换为Json字符串";

        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if(args.Count > 0) {
                return new Expr(TP.Str, toJson(args[0]));
            }
            return Expr.Err("转Json函数参数不足");
        }

        public static string toJson(Expr e) {
            switch (e.Tp) {
                case TP.Bool:
                    return Convert.ToString(e.Bool()).ToLower();

                case TP.Int:
                    return Convert.ToString(e.Int());

                case TP.Float:
                    return Convert.ToString(e.Float());

                case TP.Rune:
                    return "\"" + (Parser.Char2tranfer(e.Char()) ?? e.Char().ToString()) + "\"";

                case TP.Str:
                    return "\"" + Parser.FormStr(e.Str()) + "\"";

                case TP.Arr:
                    string arrStr = "[";
                    foreach(var item in e.List!) {
                        arrStr += toJson(item) + ", ";
                    }
                    if(e.List!.Count > 0) {
                        arrStr = arrStr[0..(arrStr.Length-2)];
                    }
                    arrStr += "]";
                    return arrStr;

                case TP.Obj:
                    string objStr = "{";
                    foreach(var item in e.Ctx().Map) {
                        objStr += "\"" + item.Key[1..] + "\": " + toJson(item.Value) + ", ";
                    }
                    if (e.Ctx().Map.Count > 0) { 
                        objStr = objStr[0..(objStr.Length-2)];
                    }
                    objStr += "}";
                    return objStr;

            }

            return "null";
        }

    }



    class ParseJson : Native {
        public override string Name { get; set; } = "解析Json";
        public override string Desc { get; set; } = "参数1-字符串，返回任意；将参数1字符串解析为对应的数据";
        public override Expr Run(List<Expr> args, Ctx ctx, Obj? obj=null, List<Expr>? namedArgs=null) {
            if (args.Count > 0 && args[0].Tp == TP.Str) {
                try {
                    string s = args[0].Str().Trim();
                    if(s == "") {
                        return Expr.NoneExpr;
                    }
                    
                    JsonNode? jn = JsonNode.Parse(s);
                    if(jn == null) {
                        return Expr.NoneExpr;
                    }
                    return JsonNode2Expr(jn);
                }catch(Exception e) {
                    return Expr.Err("解析Json函数出错，" + e.Message);
                }
                
            }
            return Expr.Err("解析Json函数参数错误");
        }



        public static Expr JsonNode2Expr(JsonNode node) {
            Expr ret = new Expr(TP.None, 0);
            if(node is JsonArray) {
                List<Expr> list = new List<Expr>();
                foreach(var item in (node as JsonArray)!) {
                    list.Add(JsonNode2Expr(item!));
                }
                ret.Tp = TP.Arr;
                ret.List = list;
                return ret;
            }else if(node is JsonObject) {
                Obj obj = new Obj(Env.UsrCtx);
                foreach(var item in (node as JsonObject)!) {
                    obj.Map["#" + item.Key] = JsonNode2Expr(item.Value!);
                }
                ret.Tp = TP.Obj;
                ret.Val = obj;
                return ret;
            } else {
                string str = node.ToJsonString();
                if (str[0] == '"') {
                    ret.Tp = TP.Str;
                    ret.Val = str[1..(str.Length-1)];
                } else if (str == "true") {
                    ret.Tp = TP.Bool;
                    ret.Val = true;
                } else if (str == "false") {
                    ret.Tp = TP.Bool;
                    ret.Val = false;
                } else if (str == "null" || str == "undefined") {
                    ret.Tp = TP.None;
                } else if (Parser.IsNumberStr(str) == 0) {
                    ret.Tp = TP.Int;
                    ret.Val = int.Parse(str);
                }else if(Parser.IsNumberStr(str) == 1) {
                    ret.Tp = TP.Float;
                    ret.Val = decimal.Parse(str);
                }

                return ret;
            }
        }




    }


}
